package optiondef

import (
	"fmt"
	"photowall/pkg/log"
	"sync"
)

func init() {
	getAlbumdbService()
}

// AlbumService interface for managing photo albums with author binding
type AlbumService interface {
	// Add a new album for a specific author
	AddAlbum(authorID string, info *AlbumInfo) (bool, error)

	// Delete an album by AuthorID and AlbumName
	DeleteAlbum(authorID string, albumName string) (bool, error)

	// Update an existing album by AuthorID and AlbumName
	UpdateAlbum(authorID string, albumName string, info *AlbumInfo) (bool, error)

	// Get all albums for a specific author by AuthorID
	GetAlbumsByAuthorID(authorID string) ([]AlbumInfo, error)

	// Check if an album exists by AuthorID and AlbumName
	IsAlbumExists(authorID string, albumName string) (bool, error)

	// Get an album by AuthorID and AlbumName
	GetAlbumByAuthorIDAndAlbumName(authorID string, albumName string) (*AlbumInfo, error)

	// Get an album by AlbumName
	GetPubAlbumByName(albumName string) ([]AlbumInfo, error)
}

type PhotoService interface {
	// Add a photo to an album by AlbumID
	AddPhotoToAlbumByAlbumID(albumID string, photo *Photoinfo) (bool, error)

	// Delete a photo by PhotoID
	DeletePhotoByPhotoID(photoID string) (bool, error)

	// Update a photo by PhotoID
	UpdatePhotoInfoByPhotoID(photoID string, photo *Photoinfo) (bool, error)

	// Get all photos in an album by AlbumID
	GetAllPhotosInAlbumByAlbumID(albumID string) ([]Photoinfo, error)

	// Get a photo by PhotoID
	GetPhotoByPhotoID(photoID string) (*Photoinfo, error)

	// GetPublicPhotosByName gets public photos by photo name
	GetPublicPhotosByName(photoName string) ([]Photoinfo, error)

	// GetUserPhotosByName gets user photos by photo name
	GetUserPhotosByName(authorID, name string) ([]Photoinfo, error)

	// GetAllPhotosInAlbumByAlbumName gets all photos in an album by AlbumName
	GetAllPhotosInAlbumByAlbumName(albumName string) ([]Photoinfo, error)

	IsPhotoOwnedByUser(photoID, userID string) (bool, error)
}

// AlbumServiceImpl implementation of AlbumService interface
type AlbumServiceImpl struct {
	dbService *albumDbService
}

// newAlbumService creates a new instance of AlbumService
func newAlbumService(dbService *albumDbService) AlbumService {
	return &AlbumServiceImpl{dbService: dbService}
}

// validateAlbumInfo validates the album information
func validateAlbumInfo(info *AlbumInfo) error {
	if info.AlbumName == "" {
		return fmt.Errorf("album name cannot be empty")
	}
	if info.Description == "" {
		return fmt.Errorf("description cannot be empty")
	}
	// 添加其他必要的校验逻辑，如长度限制、格式检查等
	return nil
}

// AddAlbum adds a new album for a specific author
func (a *AlbumServiceImpl) AddAlbum(authorID string, info *AlbumInfo) (bool, error) {
	// 校验必要字段
	if err := validateAlbumInfo(info); err != nil {
		return false, err
	}

	// 校验相册是否已经存在
	exists, err := a.IsAlbumExists(authorID, info.AlbumName)
	if err != nil {
		log.GetDatabaseLogger().Error("Failed to check album existence: " + err.Error())
		return false, fmt.Errorf("failed to check album existence: %w", err)
	}
	if exists {
		return false, fmt.Errorf("album already exists")
	}

	// 添加相册到数据库
	success, err := a.dbService.AddAlbumToDb(info)
	if err != nil {
		log.GetMainLogger().Error("Failed to add album to database: " + err.Error())
		return false, fmt.Errorf("failed to add album to database: %w", err)
	}

	return success, nil
}

// DeleteAlbum deletes an album by AuthorID and AlbumName
func (a *AlbumServiceImpl) DeleteAlbum(authorID string, albumName string) (bool, error) {
	// 校验相册是否存在
	exists, err := a.IsAlbumExists(authorID, albumName)
	if err != nil {
		log.GetDatabaseLogger().Error("Failed to check album existence: " + err.Error())
		return false, fmt.Errorf("failed to check album existence: %w", err)
	}
	if !exists {
		return false, fmt.Errorf("album does not exist")
	}

	return a.dbService.DeleteAlbumInDbByAuthorIDAndAlbumName(authorID, albumName)
}

// UpdateAlbum updates an existing album by AuthorID and AlbumName
func (a *AlbumServiceImpl) UpdateAlbum(authorID string, albumName string, info *AlbumInfo) (bool, error) {
	return a.dbService.UpdateAlbumInDbByAuthorIDAndAlbumName(authorID, albumName, info)
}

// GetAlbumsByAuthorID gets all albums for a specific author by AuthorID
func (a *AlbumServiceImpl) GetAlbumsByAuthorID(authorID string) ([]AlbumInfo, error) {
	return a.dbService.GetAlbumsByAuthIDInDb(authorID)
}

// IsAlbumExists checks if an album exists by AuthorID and AlbumName
func (a *AlbumServiceImpl) IsAlbumExists(authorID string, albumName string) (bool, error) {
	return a.dbService.IsAlbumInDbByAuthorIDAndAlbumName(authorID, albumName)
}

// GetAlbumByAuthorIDAndAlbumName gets an album by AuthorID and AlbumName
func (a *AlbumServiceImpl) GetAlbumByAuthorIDAndAlbumName(authorID string, albumName string) (*AlbumInfo, error) {
	return a.dbService.GetAlbumInfoByAuthorIDAlbumNameInMongoDB(authorID, albumName)
}

// GetPubAlbumByName retrieves albums by their name
func (a *AlbumServiceImpl) GetPubAlbumByName(albumName string) ([]AlbumInfo, error) {
	// 校验相册名是否为空
	if albumName == "" {
		return nil, fmt.Errorf("album name cannot be empty")
	}

	// 调用数据访问层的函数来获取相册信息
	albums, err := a.dbService.GetPubAlbumByNameInDb(albumName)
	if err != nil {
		log.GetDatabaseLogger().Error(fmt.Sprintf("Error retrieving albums by name: %v", err))
		return nil, fmt.Errorf("failed to retrieve albums by name: %w", err)
	}

	return albums, nil
}

// PhotoServiceImpl implementation of PhotoService interface
type PhotoServiceImpl struct {
	dbService *albumDbService
}

// GetPublicPhotosByName gets public photos by photo name
func (p *PhotoServiceImpl) GetPublicPhotosByName(photoName string) ([]Photoinfo, error) {
	return p.dbService.GetPublicPhotosByName(photoName)
}

// GetUserPhotosByName gets user photos by photo name
func (p *PhotoServiceImpl) GetUserPhotosByName(authorID, name string) ([]Photoinfo, error) {
	return p.dbService.GetUserPhotosByName(authorID, name)
}

// newPhotoService creates a new instance of PhotoService
func newPhotoService(dbService *albumDbService) PhotoService {
	return &PhotoServiceImpl{dbService: dbService}
}

// AddPhotoToAlbumByAlbumID adds a photo to an album by AlbumID
func (p *PhotoServiceImpl) AddPhotoToAlbumByAlbumID(albumID string, photo *Photoinfo) (bool, error) {
	return p.dbService.AddPhotoToAlbumByAlbumID(albumID, photo)
}

// DeletePhotoByPhotoID deletes a photo by PhotoID
func (p *PhotoServiceImpl) DeletePhotoByPhotoID(photoID string) (bool, error) {
	return p.dbService.DeletePhotoByPhotoID(photoID)
}

// UpdatePhotoInfoByPhotoID updates a photo by PhotoID
func (p *PhotoServiceImpl) UpdatePhotoInfoByPhotoID(photoID string, photo *Photoinfo) (bool, error) {
	return p.dbService.UpdatePhotoInfoByPhotoID(photoID, photo)
}

// IsPhotoOwnedByUser
func (p *PhotoServiceImpl) IsPhotoOwnedByUser(photoID, userID string) (bool, error) {
	// 验证 photoID 和 userID 的有效性
	if len(photoID) == 0 || len(userID) == 0 {
		return false, fmt.Errorf("IsPhotoOwnedByUser info is not valid")
	}

	// 调用数据访问层方法
	isOwned, err := p.dbService.IsPhotoOwnedByUser(photoID, userID)
	if err != nil {
		log.GetDatabaseLogger().Error(fmt.Sprintf("IsPhotoOwnedByUser failed, %v", err))
		return false, err
	}

	return isOwned, nil
}

// GetAllPhotosInAlbumByAlbumID gets all photos in an album by AlbumID
func (p *PhotoServiceImpl) GetAllPhotosInAlbumByAlbumID(albumID string) ([]Photoinfo, error) {
	var photos []Photoinfo
	_, err := p.dbService.GetAllPhotoInAlbumByAlbumID(photos, albumID)
	if err != nil {
		return nil, err
	}
	return photos, nil
}

// GetAllPhotosInAlbumByAlbumName gets all photos in an album by AlbumName
func (p *PhotoServiceImpl) GetAllPhotosInAlbumByAlbumName(albumName string) ([]Photoinfo, error) {
	var photos []Photoinfo
	_, err := p.dbService.GetAllPhotoInAlbumByAlbumName(photos, albumName)
	if err != nil {
		return nil, err
	}
	return photos, nil
}

// GetPhotoByPhotoID gets a photo by PhotoID
func (p *PhotoServiceImpl) GetPhotoByPhotoID(photoID string) (*Photoinfo, error) {
	return p.dbService.GetPhotoByPhotoID(photoID)
}

// photoWallService combines AlbumService and PhotoService
type photoWallService struct {
	AlbumService
	PhotoService
}

var (
	photoServiceInstant         *photoWallService
	photoServiceInstantSyncOnce sync.Once
)

// GetPhotoWallService returns a singleton instance of photoWallService
func GetPhotoWallService() *photoWallService {
	photoServiceInstantSyncOnce.Do(func() {
		dbService := getAlbumdbService()
		albumService := newAlbumService(dbService)
		photoService := newPhotoService(dbService)
		photoServiceInstant = &photoWallService{
			AlbumService: albumService,
			PhotoService: photoService,
		}
	})
	return photoServiceInstant
}

// 只能说，大模型真TM牛逼
